/**
 * 表单管理通用逻辑 Hook
 *
 * 抽取表单组件的通用业务逻辑
 * 包括验证、提交、重置等功能
 */

import { ref, reactive, computed, watch, nextTick, type Ref } from "vue";
import type { FormInstance, FormRules } from "element-plus";
import type {
  WmsFormConfig,
  WmsFormField,
  WmsFormRule,
} from "@/components/wms/types";

/**
 * 表单配置接口
 */
export interface UseFormOptions<T = any> {
  /** 初始表单数据 */
  initialData?: Partial<T>;
  /** 验证规则 */
  rules?: FormRules;
  /** 提交API函数 */
  submitApi?: (data: T) => Promise<any>;
  /** 是否立即验证 */
  validateOnMount?: boolean;
  /** 是否在规则变化时验证 */
  validateOnRuleChange?: boolean;
}

/**
 * 表单管理Hook返回值
 */
export interface UseFormReturn<T = any> {
  // 表单状态
  formData: Ref<T>;
  formRef: Ref<FormInstance | undefined>;
  loading: Ref<boolean>;
  submitting: Ref<boolean>;

  // 验证状态
  validationErrors: Ref<Record<string, string>>;
  isValid: Ref<boolean>;

  // 方法
  validate: () => Promise<boolean>;
  validateField: (field: string) => Promise<boolean>;
  clearValidation: (fields?: string[]) => void;
  resetForm: () => void;
  submit: () => Promise<boolean>;
  setFormData: (data: Partial<T>) => void;
  getFormData: () => T;
  setFieldValue: (field: string, value: any) => void;
  getFieldValue: (field: string) => any;
  setFieldError: (field: string, error: string) => void;
  clearFieldError: (field: string) => void;
}

/**
 * 表单管理通用Hook
 */
export function useForm<T extends Record<string, any> = any>(
  options: UseFormOptions<T> = {},
): UseFormReturn<T> {
  const {
    initialData = {} as T,
    rules = {},
    submitApi,
    validateOnMount = false,
    validateOnRuleChange = true,
  } = options;

  // 表单状态
  const formData = ref({ ...initialData } as T) as Ref<T>;
  const formRef = ref<FormInstance>();
  const loading = ref(false);
  const submitting = ref(false);

  // 验证状态
  const validationErrors = ref<Record<string, string>>({});
  const isValid = ref(false);

  /**
   * 验证整个表单
   */
  const validate = async (): Promise<boolean> => {
    if (!formRef.value) return false;

    try {
      await formRef.value.validate();
      isValid.value = true;
      return true;
    } catch (error) {
      isValid.value = false;
      console.warn("表单验证失败:", error);
      return false;
    }
  };

  /**
   * 验证指定字段
   */
  const validateField = async (field: string): Promise<boolean> => {
    if (!formRef.value) return false;

    try {
      await formRef.value.validateField(field);
      delete validationErrors.value[field];
      return true;
    } catch (error) {
      validationErrors.value[field] = error as string;
      return false;
    }
  };

  /**
   * 清除验证信息
   */
  const clearValidation = (fields?: string[]): void => {
    if (!formRef.value) return;

    if (fields) {
      formRef.value.clearValidate(fields);
      fields.forEach((field) => {
        delete validationErrors.value[field];
      });
    } else {
      formRef.value.clearValidate();
      validationErrors.value = {};
    }
  };

  /**
   * 重置表单
   */
  const resetForm = (): void => {
    if (formRef.value) {
      formRef.value.resetFields();
    }
    formData.value = { ...initialData } as T;
    validationErrors.value = {};
    isValid.value = false;
  };

  /**
   * 提交表单
   */
  const submit = async (): Promise<boolean> => {
    try {
      submitting.value = true;

      // 先验证表单
      const valid = await validate();
      if (!valid) {
        return false;
      }

      // 调用提交API
      if (submitApi) {
        await submitApi(formData.value);
        ElMessage.success("提交成功");
      }

      return true;
    } catch (error) {
      console.error("表单提交失败:", error);
      ElMessage.error("提交失败");
      return false;
    } finally {
      submitting.value = false;
    }
  };

  /**
   * 设置表单数据
   */
  const setFormData = (data: Partial<T>): void => {
    formData.value = { ...formData.value, ...data };
  };

  /**
   * 获取表单数据
   */
  const getFormData = (): T => {
    return { ...formData.value };
  };

  /**
   * 设置字段值
   */
  const setFieldValue = (field: string, value: any): void => {
    (formData.value as any)[field] = value;
  };

  /**
   * 获取字段值
   */
  const getFieldValue = (field: string): any => {
    return (formData.value as any)[field];
  };

  /**
   * 设置字段错误
   */
  const setFieldError = (field: string, error: string): void => {
    validationErrors.value[field] = error;
  };

  /**
   * 清除字段错误
   */
  const clearFieldError = (field: string): void => {
    delete validationErrors.value[field];
  };

  // 监听表单数据变化进行验证
  watch(
    () => formData.value,
    async () => {
      if (validateOnRuleChange && formRef.value) {
        await nextTick();
        validate();
      }
    },
    { deep: true },
  );

  return {
    // 表单状态
    formData,
    formRef,
    loading,
    submitting,

    // 验证状态
    validationErrors,
    isValid,

    // 方法
    validate,
    validateField,
    clearValidation,
    resetForm,
    submit,
    setFormData,
    getFormData,
    setFieldValue,
    getFieldValue,
    setFieldError,
    clearFieldError,
  };
}

/**
 * 表单字段动态配置Hook
 */
export function useFormFields() {
  const fields = ref<WmsFormField[]>([]);

  /**
   * 设置字段配置
   */
  const setFields = (newFields: WmsFormField[]): void => {
    fields.value = newFields;
  };

  /**
   * 添加字段
   */
  const addField = (field: WmsFormField, index?: number): void => {
    if (index !== undefined) {
      fields.value.splice(index, 0, field);
    } else {
      fields.value.push(field);
    }
  };

  /**
   * 移除字段
   */
  const removeField = (name: string): void => {
    const index = fields.value.findIndex((field) => field.name === name);
    if (index > -1) {
      fields.value.splice(index, 1);
    }
  };

  /**
   * 更新字段配置
   */
  const updateField = (name: string, updates: Partial<WmsFormField>): void => {
    const field = fields.value.find((f) => f.name === name);
    if (field) {
      Object.assign(field, updates);
    }
  };

  /**
   * 显示/隐藏字段
   */
  const toggleFieldVisible = (name: string, visible?: boolean): void => {
    const field = fields.value.find((f) => f.name === name);
    if (field) {
      field.hidden = visible !== undefined ? !visible : !field.hidden;
    }
  };

  /**
   * 启用/禁用字段
   */
  const toggleFieldDisabled = (name: string, disabled?: boolean): void => {
    const field = fields.value.find((f) => f.name === name);
    if (field) {
      field.disabled = disabled !== undefined ? disabled : !field.disabled;
    }
  };

  /**
   * 设置字段为必填
   */
  const setFieldRequired = (name: string, required: boolean): void => {
    const field = fields.value.find((f) => f.name === name);
    if (field) {
      field.required = required;
    }
  };

  /**
   * 获取可见字段
   */
  const visibleFields = computed(() => {
    return fields.value.filter((field) => !field.hidden);
  });

  /**
   * 获取启用字段
   */
  const enabledFields = computed(() => {
    return fields.value.filter((field) => !field.disabled);
  });

  /**
   * 获取必填字段
   */
  const requiredFields = computed(() => {
    return fields.value.filter((field) => field.required);
  });

  return {
    fields,
    visibleFields,
    enabledFields,
    requiredFields,
    setFields,
    addField,
    removeField,
    updateField,
    toggleFieldVisible,
    toggleFieldDisabled,
    setFieldRequired,
  };
}

/**
 * 表单验证规则生成Hook
 */
export function useFormValidation() {
  /**
   * 生成验证规则
   */
  const generateRules = (fields: WmsFormField[]): FormRules => {
    const rules: FormRules = {};

    fields.forEach((field) => {
      const fieldRules: any[] = [];

      // 必填验证
      if (field.required) {
        fieldRules.push({
          required: true,
          message: `${field.label}不能为空`,
          trigger: field.type === "input" ? "blur" : "change",
        });
      }

      // 自定义验证规则
      if (field.rules) {
        fieldRules.push(...field.rules);
      }

      // 根据字段类型添加特定验证
      switch (field.type) {
        case "email":
          fieldRules.push({
            type: "email",
            message: "请输入正确的邮箱地址",
            trigger: "blur",
          });
          break;

        case "number":
          fieldRules.push({
            type: "number",
            message: "请输入正确的数字",
            trigger: "blur",
          });
          break;

        case "url":
          fieldRules.push({
            type: "url",
            message: "请输入正确的URL地址",
            trigger: "blur",
          });
          break;
      }

      if (fieldRules.length > 0) {
        rules[field.name] = fieldRules;
      }
    });

    return rules;
  };

  /**
   * 常用验证规则
   */
  const commonRules = {
    // 手机号验证
    phone: {
      pattern: /^1[3-9]\d{9}$/,
      message: "请输入正确的手机号码",
      trigger: "blur",
    },

    // 身份证验证
    idCard: {
      pattern: /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/,
      message: "请输入正确的身份证号码",
      trigger: "blur",
    },

    // 密码强度验证
    password: {
      pattern: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d@$!%*?&]{8,}$/,
      message: "密码至少8位，包含大小写字母和数字",
      trigger: "blur",
    },

    // 中文验证
    chinese: {
      pattern: /^[\u4e00-\u9fa5]+$/,
      message: "只能输入中文",
      trigger: "blur",
    },

    // 英文验证
    english: {
      pattern: /^[a-zA-Z]+$/,
      message: "只能输入英文",
      trigger: "blur",
    },

    // 数字验证
    number: {
      pattern: /^\d+$/,
      message: "只能输入数字",
      trigger: "blur",
    },

    // 字母数字验证
    alphanumeric: {
      pattern: /^[a-zA-Z0-9]+$/,
      message: "只能输入字母和数字",
      trigger: "blur",
    },
  };

  return {
    generateRules,
    commonRules,
  };
}

/**
 * 表单联动Hook
 */
export function useFormLinkage<T extends Record<string, any> = any>(
  formData: Ref<T>,
) {
  const linkageRules = ref<
    Array<{
      watch: string[];
      handler: (values: any[], formData: T) => void;
    }>
  >([]);

  /**
   * 添加联动规则
   */
  const addLinkage = (
    watchFields: string[],
    handler: (values: any[], formData: T) => void,
  ): void => {
    linkageRules.value.push({
      watch: watchFields,
      handler,
    });

    // 立即执行一次
    const values = watchFields.map((field) => (formData.value as any)[field]);
    handler(values, formData.value);
  };

  /**
   * 移除联动规则
   */
  const removeLinkage = (watchFields: string[]): void => {
    const index = linkageRules.value.findIndex(
      (rule) =>
        rule.watch.length === watchFields.length &&
        rule.watch.every((field) => watchFields.includes(field)),
    );
    if (index > -1) {
      linkageRules.value.splice(index, 1);
    }
  };

  // 监听表单数据变化触发联动
  watch(
    () => formData.value,
    (newData) => {
      linkageRules.value.forEach((rule) => {
        const values = rule.watch.map((field) => (newData as any)[field]);
        rule.handler(values, newData);
      });
    },
    { deep: true },
  );

  return {
    addLinkage,
    removeLinkage,
  };
}

/**
 * 表单步骤管理Hook
 */
export function useFormSteps() {
  const currentStep = ref(0);
  const steps = ref<
    Array<{
      title: string;
      description?: string;
      fields: string[];
      validator?: () => Promise<boolean>;
    }>
  >([]);

  /**
   * 设置步骤配置
   */
  const setSteps = (newSteps: typeof steps.value): void => {
    steps.value = newSteps;
    currentStep.value = 0;
  };

  /**
   * 下一步
   */
  const nextStep = async (): Promise<boolean> => {
    const step = steps.value[currentStep.value];

    // 验证当前步骤
    if (step.validator) {
      const valid = await step.validator();
      if (!valid) {
        return false;
      }
    }

    if (currentStep.value < steps.value.length - 1) {
      currentStep.value++;
      return true;
    }

    return false;
  };

  /**
   * 上一步
   */
  const prevStep = (): boolean => {
    if (currentStep.value > 0) {
      currentStep.value--;
      return true;
    }
    return false;
  };

  /**
   * 跳转到指定步骤
   */
  const gotoStep = (step: number): boolean => {
    if (step >= 0 && step < steps.value.length) {
      currentStep.value = step;
      return true;
    }
    return false;
  };

  /**
   * 当前步骤信息
   */
  const currentStepInfo = computed(() => {
    return steps.value[currentStep.value];
  });

  /**
   * 是否第一步
   */
  const isFirstStep = computed(() => {
    return currentStep.value === 0;
  });

  /**
   * 是否最后一步
   */
  const isLastStep = computed(() => {
    return currentStep.value === steps.value.length - 1;
  });

  return {
    currentStep,
    steps,
    currentStepInfo,
    isFirstStep,
    isLastStep,
    setSteps,
    nextStep,
    prevStep,
    gotoStep,
  };
}
